- /* sifisdiv.cpp by K.Tsuru */
- // function ID = 428 BRADIX
- /**************************
- SInteger class
- It divides SInteger 'm' by an integer 'x'(ulong) (i.e. quot = m/x)
- and returns the remainder.
- ***************************/
- #ifndef SN_H
- #include "sn.h"
- #endif
- static const char* func = "IsDiv";
- long IsDiv(const SInteger& m, ulong x, SInteger& quot){
- if( !x ) m.SetError(m.DIVIDED_BY_ZERO, func, 428);
- //When &m == " and quot/x == 0 it yields m = 0.Then it keeps the sign.
- //The sign of m is necessary to return the remainder.
- int msgn = m.Sign(428);
- if(x == 1uL || !msgn){
- quot = m; return 0; //remainder=0
- }
- const ulong mt = m.SlOpMaxValue();
- if(x > mt) m.SetError(m.OUT_OF_RANGE, func, 428);
-
- int qh = (int)m.Head(), qt = (int)m.Tail();
- if(qh <= 1){//The figures of m is one or two.
- // s <= (B-1)*B+(B-1) = B^2 -1 < LONG_MAX
- long s = (long)m[1]*BRADIX + (long)m[0]; //It can be convert to the long value.
- quot.SetLong(s/(long)x); // size = 4
- s = s%(long)x;
- return msgn > 0 ? s : -s; //The sign of remainder is the same as that of m.
- }
- if(&m != "){
- //When &m == " it must not be executed / is not necessary.
- if(quot.Size() < m.Size()) quot.valloc(m.Size(), -1);
- //It fills the lower part with zero.
- if(qt) quot.figure.clear(quot.aTail, uint(qt-1));
- quot.figure.clear(uint(qh + 1));
- }
-
- const fType* mv = m.ReadFigures();
- fType* qv = quot.figure.Elements();
- ulong t = 0;
- #ifndef NDEBUG
- quot.figure(qh); m.figure(qh);
- #endif
- //Taking more a few figures the remainder maybe becomes zero.
- if(qt > 4) qt -= 4;
- int i;
- for(i = qh; i >= qt ; i--) {
- // t = (t << BRADIX_BITS) | mv[i]; same speed
- t = (t << BRADIX_BITS) + mv[i];
- qv[i] = fType(t/x);
- t = t - qv[i]*x; //faster than t %= x; t < x
- }
- if((i>=0) && t){
- // for( ; (i >= 0) && t; i--){
- for( ; i >= 0; i--){
- t = (t << BRADIX_BITS);
- qv[i] = fType(t/x);
- t = t - qv[i]*x;
- }
- }
- qt = (i >= 0) ? i : 0;
- //The lower part has been filled by zeros.
- //When the remainder is zero and &m == ", figure[k] = 0 for k < qt.
- //Then it is not necessary to fill zeros.
-
- //It checks the figure position. It ends by a few figures.
- while( (qh >= 0) && !qv[qh] ) qh--;
- while( (qt <= qh) && !qv[qt]) qt++;
-
- if( (qh <= 0) && !qv[0] ){
- quot.SetZero(); //It becomes zero.
- } else {
- #ifndef NDEBUG
- assert(qh >= qt);
- #endif
- //When " == &m the figure position must be decided before the sign.
- //If not, an error will occur.
- quot.aHead = (uint)qh;
- quot.aTail = (uint)qt;
- quot.SetSign(m.Sign(428));
- }
- //It reduces the size. This is necessary because the CopyValue() is not called.
- if( 2u*(quot.aHead+1) <= quot.figure.size() ) quot.DoCutDown();
-
- long rem = (long)t; // t < x <= SlOpMaxValue() < LONG_MAX
- return msgn > 0 ? rem : -rem; //The sign of remainder is the same as that of "m".
- }
sifisdiv.cpp : last modifiled at 2017/03/13 14:31:59(2,896 bytes)
created at 2016/04/25 14:53:17
The creation time of this html file is 2017/10/25 11:09:45 (Wed Oct 25 11:09:45 2017).